package com.zjzywl.smoke.task;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.zjzywl.smoke.config.BaseDataConfig;
import com.zjzywl.smoke.manager.AlarmManager;
import com.zjzywl.smoke.repository.AlarmRepository;
import com.zjzywl.smoke.repository.AlarmTypeRepository;
import com.zjzywl.smoke.repository.DeviceRepository;
import com.zjzywl.smoke.repository.DeviceStatusHistoryRepository;
import com.zjzywl.smoke.repository.DeviceStatusRepository;
import com.zjzywl.smoke.util.MQWebSocket;
import com.zjzywl.smoke.entity.Alarm;
import com.zjzywl.smoke.entity.AlarmType;
import com.zjzywl.smoke.entity.Device;
import com.zjzywl.smoke.entity.DeviceStatus;
import com.zjzywl.smoke.entity.DeviceStatusHistory;

/*
 * 离线设备巡检
 * 1、按一定时间间隔遍历数据库表，当最近一段时间内没有发现设备状态数据，认为该设备因故障离线
 * 2、首次循环，验证所有，后续根据结果调整，优化
 * */

@Component
public class DeviceOfflineInspection implements Runnable {
	public static volatile boolean stop=false;
	private boolean firstRun=true; //第一次执行线程
	
	private List<Device> devices;
	private List<DeviceStatus> deviceStatus;
	
	@Autowired
	private DeviceRepository deviceRepository;
	@Autowired
	private DeviceStatusRepository deviceStatusRepository;
	
	@Autowired
	private DeviceStatusHistoryRepository deviceStatusHistoryRepository;
	
	@Autowired
	private AlarmTypeRepository alarmTypeRepository;

	@Autowired
	private AlarmRepository alarmRepository;
	
	@Autowired
	private AlarmManager alarmManager;	
	
	public DeviceOfflineInspection() {

	}
	
	@Override
	public void run() {
		try {
			while (true) {
				startInspection();
				
				//等待10小时
				for (int i = 0; i < 36000; i++) {
					if(stop) {
						return;
					}
					
					Thread.sleep(3600*1000);
				}
				
				//Thread.sleep(3600*1000);
			}
		} catch (InterruptedException e) {
			System.out.println("离线巡检异常："+e.getMessage());
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public void startInspection() throws InterruptedException, IOException {
		System.out.println("开始设备离线巡检");
		
		//获取需要巡检的设备数据:查找3天前安装的设备，正常情况下状态表肯定有数据了
		devices = deviceRepository.findByInstallationDateBefore(getDayByFactor(-3));
		System.out.println("设备数量:"+devices.size());
		//获取有效时间段内设备数据状态:前三天开始的状态数据认为有效
		deviceStatus = deviceStatusRepository.findByReturnTimeAfter(getDayByFactor(-3));
		System.out.println("目前设备状态数量:"+deviceStatus.size());
		
		int index=-1;
		long time = System.currentTimeMillis();
		//取出设备遍历状态表，查看该设备是否在状态表中
		for (Device dev : devices) {
			if((dev.getDeviceType().getDeviceTypeId().equals(BaseDataConfig.DEVICETYPE_SMOKE)) 
				|| (dev.getDeviceType().getDeviceTypeId().equals(BaseDataConfig.DEVICETYPE_WELLLID))
				|| (dev.getDeviceType().getDeviceTypeId().equals(BaseDataConfig.DEVICETYPE_Humiture)))
			{
				index = -1;
				for (int i = 0; i < deviceStatus.size(); i++) {
					if(stop) {
						return;
					}
					Thread.sleep(5);//短暂停止
					DeviceStatus ds = deviceStatus.get(i);
					if(dev.getId()==ds.getDevice().getId()) {
						index = i;
						break;
					}
				}
				if(index>=0) {
					deviceStatus.remove(index);
				} else {
					//根据设备类型生成状态信息
					Integer status = BaseDataConfig.GS517_SMOKE_DS_TROUBLE;
					if(dev.getDeviceType().getDeviceTypeId().equals(BaseDataConfig.DEVICETYPE_WELLLID)) {//井盖
						status = BaseDataConfig.S2021D_LW_WELLLID_TROUBLE;
					} 
					if(dev.getDeviceType().getDeviceTypeId().equals(BaseDataConfig.DEVICETYPE_Humiture)) {//温湿度
						status = BaseDataConfig.LW_Humiture_TROUBLE;
					} 
					//保存历史状态信息			
					DeviceStatusHistory dsh = new DeviceStatusHistory();
					dsh.setDevCode(dev.getDevCode());
					dsh.setDevice(dev);
					dsh.setStatus(status);
					dsh.setReturnTime(new Date());
					deviceStatusHistoryRepository.save(dsh);
					
					
				//插入实时离线状态
					//根据设备类型生成状态信息
					status = BaseDataConfig.GS517_SMOKE_DS_TROUBLE;
					if(dev.getDeviceType().getDeviceTypeId().equals(BaseDataConfig.DEVICETYPE_WELLLID)) {//井盖
						status = BaseDataConfig.S2021D_LW_WELLLID_TROUBLE;
					} 	
					if(dev.getDeviceType().getDeviceTypeId().equals(BaseDataConfig.DEVICETYPE_Humiture)) {//温湿度
						status = BaseDataConfig.LW_Humiture_TROUBLE;
					} 
					
					//删除旧数据
					deviceStatusRepository.deleteByDevCode(dev.getDevCode());
					//生成新数据
					DeviceStatus newDs = new DeviceStatus();
					newDs.setDevice(dev);
					newDs.setDevCode(dev.getDevCode());
					newDs.setReturnTime(new Date());
					newDs.setStatus(status);
					deviceStatusRepository.save(newDs);
					
					
				//产生离线报警	
					AlarmType alarmType = alarmTypeRepository.findByAlarmCode(BaseDataConfig.ALARM_TROUBLE);
					if(alarmType==null){
						System.out.println("找不到编号为["+BaseDataConfig.ALARM_TROUBLE+"]的报警类型");
						return;
					}
					Alarm alarm = new Alarm(dev,alarmType);
					alarm.setAddress(dev.getAddress());
					alarm.setDevice(dev);
					alarm.setBeginTime(new Date());
					alarm.setDisposeStatus(0);
					
					//加入报警管理队列中
					Alarm newest = alarmRepository.save(alarm);
					alarmManager.occurAlarm(newest);
					
					
					//通知前端
					SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
					java.util.Date date=new java.util.Date();  
					String strDate=sdf.format(date);
					
					MQWebSocket.sendInfo(BaseDataConfig.CMD_SENDALARM+","
							+newDs.getDevice().getDevCode()+","
							+newDs.getStatus().toString()+","
							+newDs.getStatusStr()+","
							+newDs.getDevice().getLatitude()+","
							+newDs.getDevice().getLongitude()+","
							+newDs.getDevice().getDeviceName()+","
							+newDs.getDevice().getAddress()+","
							+strDate+","
							+newDs.getDevice().getLinkMain1()+","
							+newDs.getDevice().getLinkPhone1()+","
							+newDs.getDevice().getLinkMain2()+","
							+newDs.getDevice().getLinkPhone2()+","
							+newDs.getDevice().getLinkMain3()+","
							+newDs.getDevice().getLinkPhone3()+","
							+newDs.getDevice().getLinkMain4()+","
							+newDs.getDevice().getLinkPhone4());	
				}
			}
			
			
		}
	    long time1 = System.currentTimeMillis();
	    System.out.println("巡检花费时间:"+(time1-time));
	}
	
	public void stopInspection() {
		stop = true;
	}

	
	private Date getDayByFactor(int factor) {
		Date date = new Date();
		Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(calendar.DATE, factor);
        date = calendar.getTime();	
        return date;
	}
}
